<template>
  <div class="canvasContainer">
    <!--    模型展示区-->
    <div id="myViewerDiv">
    </div>
    <!-- 自定义区 -->
    <slot></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      viewer: null, // 模型环境变量
      db: {}, // 记录模型数据
      load_options: {}, // 模型加载配置项
      index: null, // 在加载过程中的当前模型索引
      select_info: [], // 选中构建信息
      timer: null,
      init: false,
      base64: null,
      ano: null,
    };
  },
  props: {
    // 模型数据
    docs: Array,
    // 配置项
    props: Object,
    // 是否开启多模型，如果开启则按顺序加载docs数组内的模型
    multiple: {
      type: Boolean,
      default: false,
    },
    // 是否开启docs变化，清理之前的模型然后重新加载新模型
    changeClean: {
      type: Boolean,
      default: false,
    },
    DbId_Array: [],

  },
  computed: {
    // 模型数组
    modelArray() {
      return this.docs || [];
    },
    // 模型配置项
    selfProps() {
      return {
        path: "path", // docs数据内得路径字段 必填
        options: "options", // docs数据内的配置项字段，此字段应是一个对象，具体看autodesk forge viewer文档
        name: "name", // 模型名称
      };
    },
  },
  watch: {
    modelArray() {
      this.changeClean && this.reloadModel();
    },
  },
  mounted() {
    this.init = true;
    this.timer = setInterval(() => {
      if (window.THREE && window.THREE.Matrix4) {
        clearInterval(this.timer);
        let mat = new window.THREE.Matrix4();
        this.load_options = {
          placementTransform: mat,
        };
        console.log('xxx', 123)
        this.initViewer();
      }
    }, 500);
  },
  beforeDestroy() {
    clearInterval(this.timer);
    this.timer = null;
    this.init = false;
    this.uploadViewer();
  },
  methods: {
    // 初始化模型加载器
    initViewer() {
      // 初始化配置项
      let options = {
        env: "Local",
        offline: "true",
        useADP: false,
      };
      let self = this;
      // 初始化
      window.Autodesk.Viewing.Initializer(options, function onInitialized() {
        //get the viewer div
        let viewerDiv = document.getElementById("myViewerDiv");
        //initialize the viewer object
        self.viewer = new window.Autodesk.Viewing.Private.GuiViewer3D(viewerDiv, {});

        // 初始化回调
        self.$emit("init", self.viewer);

        // 调用模型加载
        self.multiple ? self.orderLoading() : self.promiseEachModel(0);

        // 多模型选择构建事件监听
        self.viewer.addEventListener(
            window.Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT,
            function (event) {

              self.select_info = self.viewer.getAggregateSelection();
              // 添加蓝点
              self.$emit(
                  "partSelect",
                  event.selections,
                  event,
                  self.viewer.getAggregateSelection()
              );
            }
        );


        // 摄像头变化事件
        self.viewer.addEventListener(
            window.Autodesk.Viewing.CAMERA_CHANGE_EVENT,
            function (rvt) {
              self.$emit("cameraMove", rvt);

            }
        );

        // self.ano = annotation(self.viewer);
        // self.ano.load();
      });
    },
    /**
     * 加载模型
     * item 模型数据
     * index 模型索引
     */
    loadModel(item = {}, index = 0, successCb, errorCb) {
      let _options = Object.assign({}, this.load_options, item[this.selfProps.options]);
      index === 0
          ? this.viewer.start(item[this.selfProps.path], _options, successCb, errorCb)
          : this.viewer.loadModel(item[this.selfProps.path], _options, successCb, errorCb);

    },
    // 有序加载
    orderLoading() {
      let index_arr = Array.apply(null, Array(this.modelArray.length)).map(
          (item, index) => index
      );
      // 调用队列加载
      this.processArray(index_arr, this.promiseEachModel).then(
          (result) => {
            //全部加载完成
            this.$emit("successAll", result);
          },
          (reason) => {
            this.$emit("errorAll", reason);
          }
      );
    },
    /**
     * 顺序异步加载model
     */
    promiseEachModel(index) {
      return new Promise((resolve, reject) => {
        if (!this.modelArray[index]) return false
        let modelName = this.modelArray[index][this.selfProps.name];
        let self = this;
        this.loadModel(
            this.modelArray[index],
            index,
            _onLoadModelSuccess,
            _onLoadModelError
        );


        // 加载成功回调
        function _onLoadModelSuccess(model) {
          self.$emit("success", model);

          self.db[model.id] = model;

          // 监听model渲染完成
          self.viewer.addEventListener(
              window.Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
              _onGeometryLoaded
          );

          //map this item with the corresponding model in case of use
          self.modelArray[index].modelObj = model;
          self.init = false;
        }

        // model渲染完毕回调
        function _onGeometryLoaded(evt) {
          self.init = false;
          self.$emit("loaded", evt);

          // 移除model渲染完毕事件监听
          self.viewer.removeEventListener(
              window.Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
              _onGeometryLoaded
          );
          // 开启鼠标滚轮放大缩小反转
          // self.viewer.setReverseZoomDirection(true);
          resolve(self.modelArray[index]);
        }

        // 加载失败回调
        function _onLoadModelError(viewerErrorCode) {
          console.error(modelName + ": Load Model Error, errorCode:" + viewerErrorCode);
          self.$emit("error", modelName, viewerErrorCode);
          self.init = false;
          //any error
          reject(modelName + " Loading Failed!" + viewerErrorCode);
          // 加载失败回调结束
        }
      });
    },
    // 队列调用
    processArray(array, fn) {
      let results = [];
      return array.reduce(function (p, item) {
        return p.then(function () {
          return fn(item).then(function (data) {
            results.push(data);
            return results;
          });
        });
      }, Promise.resolve());
    },
    // 清空cad颜色
    clearColor() {
      this.viewer && this.viewer.clearThemingColors();
    },
    /**
     * 聚焦指定构件
     * dbids 构件ids
     * focal 焦距
     */
    viewerFiting(ids, focal) {
      if (!this.viewer) return;
      // 调整焦距
      let _focal = focal || this.viewer.getFocalLength();
      this.viewer.setFocalLength(_focal);
      this.viewer.fitToView(ids);
    },
    // 卸载model
    unloadModel(model) {
      this.viewer.impl.unloadModel(model || this.viewer.model);
      return Promise.resolve();
    },
    // 卸载viewer
    uploadViewer() {
      this.viewer = null;
    },
    // 获取模型信息
    getModelInfo() {
      return {
        viewer: this.viewer,
        models: this.db,
      };
    },
    // 重启模型
    reloadModel() {
      this.init = true;
      this.unloadModel().then(() => {
        this.initViewer();
      });
    },
    // 保存截图
    savePic() {
      let that = this;
      this.viewer.getScreenShot(800, 500,
          function (src) {
            var image = new Image();
            image.src = src;
            image.onload = function () {
              that.base64 = that.getBase64Image(image);
              that.$emit('savePic', that.base64)
            }
          }
      );
    },
    // 图片转换Base64
    getBase64Image(img) {
      let canvas = document.createElement("canvas");
      canvas.width = img.width;
      canvas.height = img.height;
      let ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, img.width, img.height);
      let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
      let dataURL = canvas.toDataURL("image/" + ext);
      return dataURL;
    },
    // 保存视角 - 标注
    saveCamera(index) {
      let that = this;
      let camData = {};
      let cam = that.viewer.getCamera();
      camData.position = {
        x: cam.position.x,
        y: cam.position.y,
        z: cam.position.z
      };
      camData.target = {
        x: cam.target.x,
        y: cam.target.y,
        z: cam.target.z
      };
      camData.pivot = {
        x: cam.pivot.x,
        y: cam.pivot.y,
        z: cam.pivot.z
      };
      that.$emit('saveCamera', camData, index);
    },
    // 读取视角
    readCamera(point, DbId_Array, dbid, fragId, attachment_point) {
      let that = this;
      if (!point) {
        that.$message({
          message: '当前没有已保存的视角',
          type: 'error'
        });
        return false
      }
      let angle1 = point['position'];
      let angle2 = point['target'];
      let angle3 = point['pivot'];
      let pos = new THREE.Vector3(angle1["x"], angle1["y"], angle1["z"]);
      let target = new THREE.Vector3(angle2["x"], angle2["y"], angle2["z"]);
      let pivot = new THREE.Vector3(angle3["x"], angle3["y"], angle3["z"]);

      that.viewer.navigation.setView(pos, target);// 打开后不能放大
      that.viewer.navigation.orientCameraUp(true);
      let tempAttachment_point = '';
      if (attachment_point) {
        tempAttachment_point = attachment_point.split(",");
      }
      let markData = {
        dbId: dbid,
        fragId: fragId,
        attachmentPoint: new THREE.Vector3(tempAttachment_point[0], tempAttachment_point[1], tempAttachment_point[2]),
      }
      that.viewer.select(dbid);
      // that.ano.addMarker(markData);
    },
    // 启动蓝点模式
    redEnableEdit() {
      this.clearAno();
      this.ano = annotation(this.viewer);
      this.ano.load();
      this.ano.enableEdit();
    },
    // 关闭蓝点模式
    redDisableEdit() {
      this.ano.disableEdit(); //关闭编辑模块
    },
    clearAno() {
      this.ano.clear(); //清除已选蓝点
    },
    // 获取蓝点的数据
    redGetMarkerData() {
      let redData = this.ano.getMarkerData();
      this.$emit('redData', redData);
    },
  },
}
</script>

<style scoped>

.canvasContainer {
  width: 100%;
  height: 100%;
  display: block;
}

#myViewerDiv {
  width: 100%;
  height: 100%;

}

/deep/ .adsk-viewing-viewer .adsk-toolbar {
  left: 50%;
  right: 0;
  bottom: 0.8rem;
  font-size: 0.16rem;
}

/deep/ #backBtn {
  position: absolute;
  margin-top: 0.2rem;
  right: 0.2rem;
  z-index: 9999;
  float: left;
}

</style>
